///////////////////////////////////////////////
////file: async_pass.v
////Author: Qyw
//////////////////////////////////////////////////

module async_pass(//input
					clk_1m,
					clk_250k,
					rst_n,
					oe,
					async_rxd,
					cnt,
					check_over,
					//output
					active,
					mode,
					active_check,
					chk_cnt_clr,
					any_edge,
					rxd,
					rxd_fliter
					);

input		clk_1m, //1M clock signal
			rst_n,	//async reset
			oe,		//oe signal
			check_over, //check time out
			async_rxd,	//async rxd
			clk_250k;
input	[5:0]	cnt;

output		active,	// active counter
			active_check, //in check stage active counter
			any_edge, //any edge of the rxd
			mode,	//mode signal
			chk_cnt_clr, // in check stage cnt clear signal
			rxd;// sync rxd
output      rxd_fliter; // the pin in order to change dubug the test 

reg			active,
			rxd_fliter,
			mode_flag;
			
reg [1:0]	state,
			nstate;

reg [1:0]	rxd_fliter_r;
reg	[1:0]	rxd_r;
reg [7:0]	rxd_r_clk250k;

wire		pos_edge,
			TST_st,
			check_stage,
			stIDLE,
			neg_edge;

parameter 	TH_FOU_PERD = 6'd24,
			ONE_FOU_PERD = 6'd8,
			IDLE = 2'd0,
			CHK = 2'd1,
			TST = 2'd2,
			SYNC = 2'd3;

assign rxd = rxd_r[1];
assign stIDLE = state == IDLE;
assign pos_edge = (rxd_r[1:0] == 2'b01) && (~stIDLE);
assign neg_edge = (rxd_r[1:0] == 2'b10) && (~stIDLE);
assign any_edge = pos_edge | neg_edge;
assign mode = check_stage ? 1'b0: mode_flag;
assign active_check = check_stage;
assign TST_st = state == TST;
assign check_stage = state == CHK;
assign chk_cnt_clr = any_edge & check_stage;

always @(posedge clk_1m or negedge rst_n)
	if(~rst_n)
		rxd_fliter_r <= 2'b00;
	else
		rxd_fliter_r <= {rxd_fliter_r[0], rxd_fliter};

always @(posedge clk_1m or negedge rst_n)
	if(~rst_n)
		state <= IDLE;
	else if(~oe)
		state <= IDLE;
	else
		state <= nstate;
		
always @(*)
	case(state)
		IDLE:
			if(~rxd_r[1])
				nstate = SYNC;
			else
				nstate = IDLE;
		SYNC:
			if(any_edge)
				nstate = CHK;
			else
				nstate = SYNC;
		CHK:
			if(any_edge && (cnt < ONE_FOU_PERD))
				nstate = SYNC;
			else if(any_edge && (cnt < TH_FOU_PERD))
				nstate = TST;
			else if(check_over)
				nstate = TST;
			else
				nstate = CHK;
		TST:
			nstate = TST;
	endcase

always @(posedge clk_1m or negedge rst_n)
	if(~rst_n)
		rxd_r <= 2'b11;
	else if(~oe)
		rxd_r <= 2'b11;
	else
		rxd_r <= {rxd_r[0], rxd_fliter_r[1]};

always @(posedge clk_250k or negedge rst_n)
	if(~rst_n)
		rxd_r_clk250k <= 8'hff;
	else if(~oe)
		rxd_r_clk250k <= 8'hff;
	else
		rxd_r_clk250k <= {rxd_r_clk250k[6:0], async_rxd};

always @(posedge clk_250k or negedge rst_n)
	if(~rst_n)
		rxd_fliter <= 1'b1;
	else if(~oe)
		rxd_fliter <= 1'b1;
	else if(&rxd_r_clk250k)
		rxd_fliter <= 1'b1;
	else if(~|rxd_r_clk250k)
		rxd_fliter <= 1'b0;
		
always @(posedge clk_1m or negedge rst_n)
	if(~rst_n)
		mode_flag <= 1'b0;
	else if(~oe)
		mode_flag <= 1'b0;
	else if(any_edge & check_stage)
		mode_flag <= (cnt < TH_FOU_PERD) && (cnt > ONE_FOU_PERD);
			

always @(posedge clk_1m or negedge rst_n)
	if(~rst_n)
		active <= 1'b0;
	else if(~oe)
		active <= 1'b0;
	else if(check_stage)
		active <= 1'b0;
	else if(pos_edge & TST_st)
		active <= 1'b1;


endmodule
